<template>
    <div class="slip_container" ref="slipContainerRef" @mouseenter="moveEnterScrollBar" @mousemove="mouseMoveSlider($event)"
    @mouseleave="mouseLeaveContainer" @mouseup="mouseUpSlider">
        <div class="slip_context_fixed" ref="slipContextFixedRef" @scroll="scrollWheel">
            <div class="content_span" ref="contentSpanRef" :style="contentSpanStyle">
                <slot></slot>
            </div>
        </div>
        <transition name="horizontal-slider">
            <div class="scrollbar-bar-span horizontal-bar-span" v-if="isShowScrollbar">
                <div class="scrollbar-bar-slider slider-x" ref="sliderHorizontalRef" :style="horizontalSliderStyle" @mousedown="mouseDownSliderX($event)">
                </div>
            </div>
        </transition>
        <transition name="horizontal-slider">
            <div class="bt_arrows bt_arrows_left" ref="btArrowsLeftRef" v-if="isShowScrollbar" @click="buttonArrow(1)">
                <i class="fas fa-angle-left"></i>
            </div>
        </transition>
        <transition name="horizontal-slider">
            <div class="bt_arrows bt_arrows_right" ref="btArrowsRightRef" v-if="isShowScrollbar" @click="buttonArrow(2)">
                <i class="fas fa-angle-right"></i>
            </div>
        </transition>
    </div>
</template>
<script>
import '@fortawesome/fontawesome-free/js/all'

export default {
    name: "cross-slip",
    props: {
        scrollHeight: {
            type: Number,
            default: 6
        },
        arrowColor: {
            type: String,
            default: '#8c939d'
        },
        activeArrowColor:{
            type: String,
            default: '#6b7380'
        },
        sliderColor: {
            type: String,
            default: '#8c939d'
        },
        activeSliderColor : {
            type : String,
            default : '#6b7380'
        },
    },
    data: function(){
        return {
            contentSpanStyle: {
                width : 'auto',
                height : 'auto',
                borderBottom : '0px',
                borderLeft : '0px',
                display : 'inline-block'
            },
            horizontalSliderStyle: {
                width: '0px',
                height: this.scrollHeight + 'px',
                marginLeft: '0px',
                background: 'none',
                marginBottom: '1px'
            },

            setArrowColor: this.arrowColor,
            setActiveArrowColor: this.activeArrowColor,
            setSliderColor: this.sliderColor,
            setActiveSliderColor: this.activeSliderColor,

            isShowScrollbar: false,                         // 是否显示滚动条
            isSelectScrollbar: false,                       // 是否选中滚动条                  
            isCanMove: false,                               // 滚动条是否可以移动
            slider: {
                moveX: 0,
                downX: 0,
            },
            arrowSizeMax: 30,
            observers: []
        }
    },
    components: {
        
    },
    methods: {
        scrollWheel: function(){
            setSliderSite(this);
        },
        mouseDownSliderX: function(event){
            this.horizontalSliderStyle.background = this.setActiveSliderColor;
            this.slider.downX = event.screenX;
            this.isSelectScrollbar = true;
        },
        
        mouseMoveSlider: function(event){
            if(this.isCanMove && this.isSelectScrollbar){
                const curX = event.screenX;
                const preX = this.slider.downX;
                const moveX = curX - preX;

                setSliderMove(this, moveX);
            }
        },
        moveEnterScrollBar: function(){
            if(this.isCanMove){
                this.isShowScrollbar = true;
            }
        },
        mouseLeaveContainer: function(){
            //重置操作
            resetContainerOperate(this);
            //隐藏滚动条
             this.isShowScrollbar = false;
        },
        mouseUpSlider: function(){
            this.horizontalSliderStyle.background = this.setSliderColor;
            this.isSelectScrollbar = false;
        },
        buttonArrow: function(type){
            if(!this.isCanMove){
                return;
            }
            this.$refs['btArrowsLeftRef'].style.color = this.setActiveArrowColor;
            this.$refs['btArrowsRightRef'].style.color = this.setActiveArrowColor;

            const contentSpanWidth = this.$refs['contentSpanRef'].offsetWidth;
            const containerWidth = this.$refs['slipContainerRef'].offsetWidth;
            const sliderXWidth = this.$refs['sliderHorizontalRef'].offsetWidth;
            const times = Math.ceil(contentSpanWidth / containerWidth);
            const moveDistince = (contentSpanWidth - containerWidth) / (times - 1) / (contentSpanWidth - containerWidth) * (containerWidth - sliderXWidth);
            if(type === 1){
                // to left
                setSliderMove(this, -1 * moveDistince);
            }else {
                // to right
                setSliderMove(this, moveDistince);
            }
        }
    },
    mounted: function(){
        listenContentElement(this);
    },
    destroyed: function(){
        //销毁
        //取消监听，否则页面跳转可能会报错
        for(let i=0;i<this.observers.length;i++){
            let observer = this.observers[i];
            observer.disconnect();
        }
    }
}


function listenContentElement(app) {
    const contentSpan = app.$refs['contentSpanRef'];
    elementResizeListern(app, contentSpan, function(){
        setHorizontalSliderStyle(app);
    });
    const slipContainer = app.$refs['slipContainerRef'];
    elementResizeListern(app, slipContainer, function(){
        setHorizontalSliderStyle(app);
    });
}

/**
 * 计算横向滑块的长度及位置。
 * 滑块的长度 = 
 * @param 应用对象
 */
function setHorizontalSliderStyle(app) {
    if(app.$refs['slipContextFixedRef'] == null || app.$refs['contentSpanRef'] == null){
        return;
    }
    //计算滑块的长度
    const slipContainerWeight = app.$refs['slipContextFixedRef'].offsetWidth;
    const contentSpanWeight = app.$refs['contentSpanRef'].offsetWidth;
    if(slipContainerWeight > contentSpanWeight){
        app.isCanMove = false;
    }else{
        app.isCanMove = true;
    }

    if(app.isCanMove){
        //横向滚动条长度
        app.horizontalSliderStyle.width = slipContainerWeight / contentSpanWeight * slipContainerWeight + 'px';

        //设置按钮的位置
        if(app.$refs['slipContainerRef'] && app.$refs['btArrowsLeftRef']){
            let containerHeight = app.$refs['slipContainerRef'].clientHeight;
            let arrowHeight = 0;
            if(containerHeight / 2 >= app.arrowSizeMax){
                arrowHeight = app.arrowSizeMax;
            }else{
               arrowHeight = containerHeight / 2;
            }
            app.$refs['btArrowsLeftRef'].style.height = arrowHeight + 'px';
            app.$refs['btArrowsRightRef'].style.height = arrowHeight + 'px';

            app.$refs['btArrowsLeftRef'].style.fontSize = arrowHeight + 'px';
            app.$refs['btArrowsRightRef'].style.fontSize = arrowHeight + 'px';

            app.$refs['btArrowsLeftRef'].style.top = containerHeight / 2 - arrowHeight / 2 + 'px';
            app.$refs['btArrowsRightRef'].style.top = containerHeight / 2 - arrowHeight / 2 + 'px';

            app.$refs['btArrowsLeftRef'].style.color = app.arrowColor;
            app.$refs['btArrowsRightRef'].style.color = app.arrowColor;
        }

        //滚动条的位置
        const sliderCanMove = slipContainerWeight - ( slipContainerWeight / contentSpanWeight * slipContainerWeight );
        const scrollCanMoveX = contentSpanWeight - slipContainerWeight;
        const sliderLeft = app.$refs['slipContextFixedRef'].scrollLeft;
        const curSiteX = sliderLeft / scrollCanMoveX * sliderCanMove;
        app.horizontalSliderStyle.marginLeft = curSiteX + 'px';
    }
    
}

/**
 * 监听标签大小的变化
 * @param app 
 * @param element 监听的标签
 * @param callBack 回调方法
 * @return observer 监听对象
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function elementResizeListern(app, element, callBack) {
    const observer = new MutationObserver(function(mutationsList, observer){
        for(let mutation of mutationsList){
            if(mutation.type === 'attributes' && callBack != null){
                callBack();
            }
        }
    });
    observer.observe(element,  {attributes: true, childList: false, subtree: true});
    app.observers.push(observer);
        
    const objEl = document.createElement('object');
    objEl.setAttribute('style',
        'display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden;opacity: 0; pointer-events: none; z-index: -10;');
    objEl.type='text/html';
    element.appendChild(objEl);
    objEl.data = 'about:blank';
    objEl.onload = function(){
        this.contentDocument.defaultView.addEventListener('resize',function(e){
            if(callBack != null){
                callBack();
            }
        });
    }
}

/**
 * 重置操作信息。
 * @param app 
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function resetContainerOperate(app) {
    app.isEnterContainer = false;
    app.horizontalSliderStyle.background = app.setSliderColor;
    app.isShowScrollbar = false;
    app.isSelectScrollbar = false;
}

/**
 * 设置滚动条的移动
 * @param app
 * @param moveX 横向移动的距离
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function setSliderMove(app, moveX) {
    if(app.$refs['sliderHorizontalRef'] == null || app.$refs['slipContainerRef'] == null || app.$refs['contentSpanRef'] == null ||
    app.$refs['slipContextFixedRef'] == null){
        return;
    }
    const sliderXWidth = app.$refs['sliderHorizontalRef'].offsetWidth;
    const containerWidth = app.$refs['slipContainerRef'].offsetWidth;
    const sliderCanMove = containerWidth - sliderXWidth;
    const contentSpanWidth = app.$refs['contentSpanRef'].offsetWidth;
    const scrollCanMoveX = contentSpanWidth - containerWidth;
    const scrollX = moveX / sliderCanMove * scrollCanMoveX;

    app.slider.downX =  app.slider.downX + moveX;
    const sliderLeft = app.$refs['slipContextFixedRef'].scrollLeft;
    app.slider.moveX = sliderLeft + scrollX

    app.$refs['slipContextFixedRef'].scrollTo(app.slider.moveX,0);
}

/**
 * 设置滚动条的位置
 * @param app
 * 
 * @auth zhouhui
 * @since 1.0.0
 */
function setSliderSite(app){
    if(app.isShowScrollbar){
        if(app.$refs['slipContextFixedRef'] == null || app.$refs['sliderHorizontalRef'] == null || 
        app.$refs['slipContainerRef'] == null || app.$refs['contentSpanRef'] == null){
            return;
        }
        const sliderLeft = app.$refs['slipContextFixedRef'].scrollLeft;
        const sliderXWidth = app.$refs['sliderHorizontalRef'].offsetWidth;
        const containerWidth = app.$refs['slipContainerRef'].offsetWidth;
        const sliderCanMove = containerWidth - sliderXWidth;
        const contentSpanWidth = app.$refs['contentSpanRef'].offsetWidth;
        const scrollCanMoveX = contentSpanWidth - containerWidth;
        let curSiteX = 0;
        if(sliderCanMove > 0){
            curSiteX = sliderLeft / scrollCanMoveX * sliderCanMove;
        }
        app.horizontalSliderStyle.marginLeft = curSiteX + 'px';
    }
}
</script>

<style>
    .slip_container{
        position: relative;
        width: 100%;
        height: 100%;
        overflow: hidden;
        user-select : none;
    }
    .slip_container .slip_context_fixed{
        width: 100%;
        height: calc(100% + 25px);
        overflow-y: hidden;
        overflow-x: scroll;
    }
    .slip_context_fixed .content_span{
        position: relative;
    }
    .slip_container .scrollbar-bar-span{
        position: absolute;
        display: flex;
        z-index: 100;
    }
    .slip_container .horizontal-bar-span{
        flex-direction: row;
        width: 100%;
        height: auto;
        bottom: 0px;
        left: 0px;
        z-index: 10;
    }
    .slip_container .scrollbar-bar-slider{
        position: relative;
        margin-left: auto;
        margin-right: auto;
        border-radius: 2px 2px 2px 2px;
        cursor: pointer;
        overflow: hidden;
    }
    .bt_arrows {
        width: auto;
        height: 20px;
        position: absolute;
        display: flex;
        flex-direction: row;
        justify-items: center;
        align-items: center;
        z-index: 200;
        top: 0px;
        font-size: 20px;
        cursor: pointer;
    }
    .bt_arrows_left {
        left: 5px;
    }
    .bt_arrows_right {
        right: 5px;
    }
    .vertical-slider-enter-active, .vertical-slider-leave-active,
    .horizontal-slider-enter-active, .horizontal-slider-leave-active{
        transition : opacity 0.5s;
    }
    .vertical-slider-enter, .vertical-slider-leave-to,
    .horizontal-slider-enter, .horizontal-slider-leave-to
    {
        opacity : 0;
    }
</style>